<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>添加已有元素至末尾</title>
    <style type="text/css">
        .wrapper {
            border: 1px solid blue;
            overflow: auto;
        }
        
        .wrapper>* {
            float: left;
            margin: 10px 0px 10px 10px;
        }
        
        .wrapper>span {
            width: 100px;
            height: 100px;
            text-align: center;
            line-height: 100px;
            font-size: 30px;
        }
        
        .wrapper>span:nth-child(2n+1) {
            background: #fa9696;
        }
        
        .wrapper>span:nth-child(2n) {
            background: #9696fa;
        }
    </style>

    <script>
        window.x = {
            /* 用来保存定时器的变量 */
            timer: null,
            /* 使用函数计算一个时间点，到这个时间点后停止"移动"元素 */
            instant: 0,
            /* 用来"移动"元素的函数 */
            move: function() {
                let p = document.querySelector('.wrapper');
                let f = p.firstElementChild;
                p.appendChild(f);
                // 因为setInterval周期性调用该函数时，
                // 函数内的this不再是原来的实例(即不再表示x所引用的实例)
                // 此时需要通过 window.x 来获得原来的实例
                if (Date.now() >= window.x.instant) {
                    console.log('清除定时器');
                    window.clearInterval(window.x.timer);
                }
            },
            /* 用来启动移动过程的函数 */
            start: function() {
                // 如果再次点击按钮，则将之前的定时器清除
                if (this.timer) {
                    window.clearInterval(this.timer);
                }

                // 利用 IIFE 来计算定时器的终止时刻
                this.instant = (function() {
                    let t = new Date();
                    console.log(t);
                    t.setHours(19);
                    t.setMinutes(03);
                    t.setSeconds(40);
                    t.setMilliseconds(0);
                    console.log(t);
                    let ms = t.getTime();
                    return ms;
                })();

                // 用setInterval或setTimeout调用函数时，函数内部的this不是原来的实例
                // 比如这里的this.move函数被setInterval调用后，move函数内部的this居然是window
                this.timer = window.setInterval(this.move, 500);
                console.log(this === x);
            }
        }
    </script>
</head>

<body>
    <div class="wrapper">
        <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
    </div>
    <div class="wrapper">
        <button type="button" onclick="x.start()">"移动"元素</button>
    </div>
</body>

</html>